package com.dzm.xgb.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dzm.common.exception.Assert;
import com.dzm.common.result.ResponseEnum;
import com.dzm.xgb.core.enums.TransTypeEnum;
import com.dzm.xgb.core.hfb.FormHelper;
import com.dzm.xgb.core.hfb.HfbConst;
import com.dzm.xgb.core.hfb.RequestHelper;
import com.dzm.xgb.core.pojo.entity.TransFlow;
import com.dzm.xgb.core.pojo.entity.UserAccount;
import com.dzm.xgb.core.mapper.UserAccountMapper;
import com.dzm.xgb.core.pojo.entity.UserInfo;
import com.dzm.xgb.core.service.TransFlowService;
import com.dzm.xgb.core.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dzm.xgb.core.service.UserInfoService;
import com.dzm.xgb.core.utils.LendNoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author Dzm
 * @since 2024-08-27
 */
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private TransFlowService transFlowService;

    /**
     * 生成充值表单
     * @param chargeAmt
     * @param userId
     * @return
     */
    @Override
    public String commitCharge(BigDecimal chargeAmt, Long userId) {
        Assert.isTrue(chargeAmt.compareTo(new BigDecimal(0)) > 0, ResponseEnum.CHARGE_LESS);

        UserInfo userInfo = userInfoService.getById(userId);
        String bindCode = userInfo.getBindCode();
        Assert.notEmpty(bindCode, ResponseEnum.USER_NO_BIND_ERROR);

        Map<String, Object> param = new HashMap<>();
        param.put("agentId", HfbConst.AGENT_ID);
        param.put("agentBillNo", LendNoUtils.getLendNo());
        param.put("bindCode", bindCode);            //绑定码
        param.put("chargeAmt", chargeAmt);          //充值金额
        param.put("feeAmt", new BigDecimal(0)); //手续费
        param.put("notifyUrl", HfbConst.RECHARGE_NOTIFY_URL);
        param.put("returnUrl", HfbConst.RECHARGE_RETURN_URL);
        param.put("timestamp", RequestHelper.getTimestamp());
        param.put("sign",RequestHelper.getSign(param));  //签名字符串

        String formStr = FormHelper.buildForm(HfbConst.RECHARGE_URL, param);
        return formStr;
    }

    @Override
    public String notifyUserAccount(Map<String, Object> map) {
        String bindCode = (String) map.get("bindCode");
        BigDecimal chargeAmt = new BigDecimal((String) map.get("chargeAmt"));
        String transNo = (String) map.get("agentBillNo");

        //获取当前绑定号对应用户
        UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getBindCode, bindCode));

        //在流水表中查询是否有记录，有则说明已经回调过了
        TransFlow transFlow = transFlowService.getOne(new LambdaQueryWrapper<TransFlow>()
                .eq(TransFlow::getTransNo, transNo));
        if(transFlow != null) {
            return "success";
        }
        //修改用户账户资金
        baseMapper.updateUserAccount(userInfo.getId(), chargeAmt, new BigDecimal(0));

        //修改成功并生成流水
        transFlow = new TransFlow();
        transFlow.setMemo("充值");
        transFlow.setTransAmount(chargeAmt);
        transFlow.setTransNo(transNo);
        transFlow.setTransType(TransTypeEnum.RECHARGE.getTransType());
        transFlow.setTransTypeName(TransTypeEnum.getTransTypeName(transFlow.getTransType()));
        transFlow.setUserId(userInfo.getId());
        transFlow.setUserName(userInfo.getName());
        transFlowService.save(transFlow);

        return "success";
    }

    @Override
    public BigDecimal getAccount(Long userId) {
        UserAccount userAccount = this.getOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, userId));

        return userAccount.getAmount();
    }

    /**
     *
     * @param chargeAmt        资金变动
     * @param bindCode  用户的绑定协议号
     * @param freezeAmt       冻结资金变动
     */
    @Override
    public void updateUserAccount(String bindCode, BigDecimal chargeAmt,  BigDecimal freezeAmt) {
        UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getBindCode, bindCode));
        baseMapper.updateUserAccount(userInfo.getId(), chargeAmt, freezeAmt);
    }

    @Override
    public String commitWithdraw(Long userId, BigDecimal fetchAmt) {
        UserInfo userInfo = userInfoService.getById(userId);
        String bindCode = userInfo.getBindCode();

        Map<String, Object> param = new HashMap<>();
        param.put("agentId", HfbConst.AGENT_ID);
        param.put("agentBillNo", LendNoUtils.getWithdrawNo());
        param.put("bindCode", bindCode);    //绑定码
        param.put("fetchAmt", fetchAmt);    //提现金额
        param.put("feeAmt", new BigDecimal(0));
        param.put("notifyUrl", HfbConst.WITHDRAW_NOTIFY_URL);
        param.put("returnUrl", HfbConst.WITHDRAW_RETURN_URL);
        param.put("timestamp", RequestHelper.getTimestamp());
        param.put("sign", RequestHelper.getSign(param));

        String formStr = FormHelper.buildForm(HfbConst.WITHDRAW_URL, param);
        return formStr;
    }

    @Transactional
    @Override
    public String notifyWithdraw(Map<String, Object> map) {
        String bindCode = (String) map.get("bindCode");
        BigDecimal fetchAmt = new BigDecimal((String) map.get("fetchAmt"));
        String transNo = (String) map.get("agentBillNo");

        //幂等性校验
        TransFlow transFlow = transFlowService.getOne(new LambdaQueryWrapper<TransFlow>()
                .eq(TransFlow::getTransNo, transNo));
        if(transFlow != null) {
            return "success";
        }

        //资金修改
        UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getBindCode, bindCode));
        updateUserAccount(bindCode, fetchAmt.negate(), BigDecimal.ZERO);

        //添加交易流水
        transFlow = new TransFlow();
        transFlow.setMemo("提现");
        transFlow.setTransAmount(fetchAmt);
        transFlow.setTransNo(transNo);
        transFlow.setTransType(TransTypeEnum.WITHDRAW.getTransType());
        transFlow.setTransTypeName(TransTypeEnum.getTransTypeName(transFlow.getTransType()));
        transFlow.setUserId(userInfo.getId());
        transFlow.setUserName(userInfo.getName());
        transFlowService.save(transFlow);

        return "success";
    }
}
